<?php
class DataListSearchForm extends Form {
	private static $page_length = 10;
	private static $allowed_export = true;
	
    protected $extraClasses = array('datalist-search' => 'datalist-search');
    /**
     * @var int $pageLength How many results are shown per page.
     * Relies on pagination being implemented in the search results template.
     */
    protected $pageLength;
	protected $allowedExport;
    protected $sourceFilter;
	protected $sourceLimit;
    
    /**
     * 
     * @param Controller $controller
     * @param string $name The name of the form (used in URL addressing)
     * @param FieldList $fields Optional, defaults to a single field named "Search". Search logic needs to be customized
     *  if fields are added to the form.
     * @param FieldList $actions Optional, defaults to a single field named "Go".
     */
    public function __construct($controller, $name, $sourceClass, $sourceFilter, $fields = null, $actions = null) {
        if(!$fields) {
            $fields = new FieldList(
                new TextField('Search', _t('DataListSearchForm.SEARCH', 'Search'))
            );
        }
        
        if(!$actions) {
            $actions = new FieldList(
                new FormAction("doSearch", _t('DataListSearchForm.BUTTONSEARCH', 'Search'))
            );
        }
		
		$this->setPageLength($this->config()->get('page_length'));
		$this->setAllowedExport($this->config()->get('allowed_export'));
        
        $dataField = new DataListField('DataList', $sourceClass);
        $dataField->setPageSize($this->getPageLength());
		$dataField->setAllowedExport($this->getAllowedExport());
        $fields->push($dataField);
        
        $this->sourceFilter = $sourceFilter;
        
        parent::__construct($controller, $name, $fields, $actions);
        
        Requirements::javascript(THIRDPARTY_DIR . '/jquery/jquery.js');
        Requirements::add_i18n_javascript(SAPPHIRE_DIR . '/javascript/lang');
        Requirements::javascript('datalist/javascript/DataListField.js');
        Requirements::css('datalist/css/DataListField.css');
        
        $data = Session::get("SearchFormInfo.{$this->getController()->ClassName}.data");
        if($data){
            $this->loadDataFrom($data);
        }
    }
    
    public function getDataField(){
        return $this->Fields()->dataFieldByName('DataList');
    }
    
    public function getDataClass(){
        return $this->Fields()->dataFieldByName('DataList')->sourceClass();
    }
    
    public function setDataFieldList($field_list){
        $this->getDataField()->setFieldList($field_list);
        return $this;
    }
    
    public function setFieldCasting($field_casting){
        $this->getDataField()->setFieldCasting($field_casting);
        return $this;
    }
    
    public function doSearch($data, $form){
        Session::clear("SearchFormInfo.{$this->getController()->ClassName}.data");
        Session::set("SearchFormInfo.{$this->getController()->ClassName}.data", $data);
        return $this->controller->redirectBack();
    }
    
    public function getData(){
        $fields = $this->Fields();
        $searchData = array();
        if(sizeof($fields)){
            $obj = singleton($this->getDataField()->sourceClass());
            foreach($fields as $field){
            	if(($fieldPos = strpos($field->getName(), '__'))!==false) {
					$relation = substr($field->getName(), 0, $fieldPos);
					$relation_class = $obj->getRelationClass($relation);
					if($relation_class && $dbfield = singleton($relation_class)->dbObject(substr($field->getName(), $fieldPos + 2))){
						$searchData[str_replace('__', '.', $field->getName())] = array('value' => $field->dataValue(), 'data_type' => $dbfield->class, 'field_type' => $field->class);
					}
				}
				else {
	                if($dbfield = $obj->dbObject($field->getName())) {
	                    $searchData[$field->getName()] = array('value' => $field->dataValue(), 'data_type' => $dbfield->class, 'field_type' => $field->class);
	                }
				}
            }
        }

        return $searchData;
    }
	
	public function getDataList(){
		$data = $this->getData();
        $searchFilter = array();
		$dateRangeFilter = array();
        if(sizeof($data)){
            foreach($data as $name => $field){
                if($field['value'] != '') {
                    if($field['data_type'] == 'Date' || $field['data_type'] == 'SS_Datetime' || $field['data_type'] == 'Datetime'){
                    	if($field['field_type'] == 'DateRangeField'){
                    		$date = new Date();
	                        $date->setValue($field['value']['_Start']);
                    		$searchFilter[sprintf('%s:GreaterThanOrEqual', $name)] = $date->URLDate() .' 00:00:00';
							$date = new Date();
	                        $date->setValue($field['value']['_End']);
							$searchFilter[sprintf('%s:LessThanOrEqual', $name)] = $date->URLDate() .' 23:59:59';
                    	} else {
	                        $date = new Date();
	                        $date->setValue($field['value']);
	                        $searchFilter[sprintf('%s:StartsWith', $name)] = $date->URLDate();
						}
                    }
                    else{
                        $searchFilter[$name] = $field['value'];
                    }
                }
            }
        }

        $datalist = DataList::create($this->getDataClass())->filter(array_merge($searchFilter, $this->sourceFilter));
		if($limit = $this->getSourceLimit()){
			$datalist = $datalist->limit($limit);
		}
		return $datalist;
	}

    public function getResults(){
        return $this->getDataField()->setCustomQuery($this->getDataList())->FieldHolder();
    }
	
	/**
     * Set the limit number of records.
     * 
     * @param int $limit
     */
    public function setSourceLimit($limit) {
        $this->sourceLimit = $limit;
        return $this;
    }
    
    /**
     * @return int
     */
    public function getSourceLimit() {
        return $this->sourceLimit;
    }
    
    /**
     * Set the maximum number of records shown on each page.
     * 
     * @param int $length
     */
    public function setPageLength($length) {
        $this->pageLength = $length;
        return $this;
    }
    
    /**
     * @return int
     */
    public function getPageLength() {
        return $this->pageLength;
    }
	
	/**
     * Set the maximum number of records shown on each page.
     * 
     * @param int $length
     */
    public function setAllowedExport($allowed) {
        $this->allowedExport = $allowed;
        return $this;
    }
    
    /**
     * @return int
     */
    public function getAllowedExport() {
        return $this->allowedExport;
    }
}